{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "FhGuhbZ6M5tl"
   },
   "source": [
    "##### Copyright 2018 The TensorFlow Authors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "cellView": "form",
    "colab": {},
    "colab_type": "code",
    "id": "AwOEIRJC6Une"
   },
   "outputs": [],
   "source": [
    "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "# https://www.apache.org/licenses/LICENSE-2.0\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "cellView": "form",
    "colab": {},
    "colab_type": "code",
    "id": "KyPEtTqk6VdG"
   },
   "outputs": [],
   "source": [
    "#@title MIT License\n",
    "#\n",
    "# Copyright (c) 2017 François Chollet\n",
    "#\n",
    "# Permission is hereby granted, free of charge, to any person obtaining a\n",
    "# copy of this software and associated documentation files (the \"Software\"),\n",
    "# to deal in the Software without restriction, including without limitation\n",
    "# the rights to use, copy, modify, merge, publish, distribute, sublicense,\n",
    "# and/or sell copies of the Software, and to permit persons to whom the\n",
    "# Software is furnished to do so, subject to the following conditions:\n",
    "#\n",
    "# The above copyright notice and this permission notice shall be included in\n",
    "# all copies or substantial portions of the Software.\n",
    "#\n",
    "# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n",
    "# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n",
    "# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n",
    "# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n",
    "# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n",
    "# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n",
    "# DEALINGS IN THE SOFTWARE."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "EIdT9iu_Z4Rb"
   },
   "source": [
    "# Предсказывай расход топлива: регрессия"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "bBIlTPscrIT9"
   },
   "source": [
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/keras/basic_regression\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />Читай на TensorFlow.org</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/ru/tutorials/keras/basic_regression.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Запусти в Google Colab</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/ru/tutorials/keras/basic_regression.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />Изучай код на GitHub</a>\n",
    "  </td>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "AHp3M9ZmrIxj"
   },
   "source": [
    "Говоря о задачах *регрессии*, мы преследуем цель дать прогноз какого-либо значения, например цену или вероятность. Это уже совсем другая задача если сравненить с *классификацией*, где нужно предсказать конкретный класс или категорию (например, яблоко или апельсин на картинке).\n",
    "\n",
    "Мы будем использовать классический датасет [Auto MPG](https://archive.ics.uci.edu/ml/datasets/auto+mpg) и построим модель, которая будет предсказывать эффективность расхода топлива автомобилей конца 70-х и начала 80-х. Для этого мы загрузим описания множества различных автомобилей того времени. Эти описания будут содержать такие параметры как количество цилиндров, лошадиных сил, объем двигателя и вес.\n",
    "\n",
    "В этом примере используется `tf.keras` API, подробнее [смотри здесь](https://www.tensorflow.org/guide/keras)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "moB4tpEHxKB3"
   },
   "outputs": [],
   "source": [
    "# Установим библиотеку seaborn для построения парных графиков\n",
    "!pip install seaborn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "1rRo8oNqZ-Rj"
   },
   "outputs": [],
   "source": [
    "from __future__ import absolute_import, division, print_function\n",
    "\n",
    "import pathlib\n",
    "\n",
    "import pandas as pd\n",
    "import seaborn as sns\n",
    "\n",
    "import tensorflow as tf\n",
    "from tensorflow import keras\n",
    "from tensorflow.keras import layers\n",
    "\n",
    "print(tf.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "F_72b0LCNbjx"
   },
   "source": [
    "## Датасет Auto MPG\n",
    "\n",
    "Датасет доступен в [репозитарии машинного обучения UCI](https://archive.ics.uci.edu/ml/datasets/auto+mpg).\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "gFh9ne3FZ-On"
   },
   "source": [
    "### Загружаем данные\n",
    "Сперва загрузим наш набор данных:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "p9kxxgzvzlyz"
   },
   "outputs": [],
   "source": [
    "dataset_path = keras.utils.get_file(\"auto-mpg.data\", \"https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data\")\n",
    "dataset_path"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "nslsRLh7Zss4"
   },
   "source": [
    "Импортируем его при помощи библиотеки Pandas:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "CiX2FI4gZtTt"
   },
   "outputs": [],
   "source": [
    "column_names = ['Расход топлива','Кол-во цилиндров','Объем двигателя','Л.с.','Вес',\n",
    "                'Разгон до 100 км/ч', 'Год выпуска', 'Страна выпуска'] \n",
    "raw_dataset = pd.read_csv(dataset_path, names=column_names,\n",
    "                      na_values = \"?\", comment='\\t',\n",
    "                      sep=\" \", skipinitialspace=True)\n",
    "\n",
    "dataset = raw_dataset.copy()\n",
    "dataset.tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "3MWuJTKEDM-f"
   },
   "source": [
    "### Подготовим данные\n",
    "\n",
    "Нам нужно почистить наши данные, так как датасет содержит несколько неизвестных значений:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "JEJHhN65a2VV"
   },
   "outputs": [],
   "source": [
    "dataset.isna().sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "9UPN0KBHa_WI"
   },
   "source": [
    "Чтобы было проще давай просто удалим ряды, где отсутствуют значения:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "4ZUDosChC1UN"
   },
   "outputs": [],
   "source": [
    "dataset = dataset.dropna()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "8XKitwaH4v8h"
   },
   "source": [
    "`\"Страна выпуска\"` - это колонка с указанием категории, а не значений. Давай переведем ее в двоичный код:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "gWNTD2QjBWFJ"
   },
   "outputs": [],
   "source": [
    "origin = dataset.pop('Страна выпуска')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "ulXz4J7PAUzk"
   },
   "outputs": [],
   "source": [
    "dataset['США'] = (origin == 1)*1.0\n",
    "dataset['Европа'] = (origin == 2)*1.0\n",
    "dataset['Япония'] = (origin == 3)*1.0\n",
    "dataset.tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Cuym4yvk76vU"
   },
   "source": [
    "### Разделим на тренировочные и проверочные данные\n",
    "\n",
    "Теперь нам необходимо разделить данные на две части: для обучения и для проверки.\n",
    "\n",
    "Точность получившейся модели мы сможем проверить на втором наборе данных."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "qn-IGhUE7_1H"
   },
   "outputs": [],
   "source": [
    "train_dataset = dataset.sample(frac=0.8,random_state=0)\n",
    "test_dataset = dataset.drop(train_dataset.index)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "J4ubs136WLNp"
   },
   "source": [
    "### Проверим данные\n",
    "\n",
    "Давай посмотрим на совместное распределение нескольких пар колонок из тренировочного набора данных:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "oRKO_x8gWKv-"
   },
   "outputs": [],
   "source": [
    "sns.pairplot(train_dataset[[\"Расход топлива\", \"Кол-во цилиндров\", \"Объем двигателя\", \"Вес\"]], diag_kind=\"kde\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "gavKO_6DWRMP"
   },
   "source": [
    "А также посмотрим как выглядит общая статистика:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "yi2FzC3T21jR"
   },
   "outputs": [],
   "source": [
    "train_stats = train_dataset.describe()\n",
    "train_stats.pop(\"Расход топлива\")\n",
    "train_stats = train_stats.transpose()\n",
    "train_stats"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Db7Auq1yXUvh"
   },
   "source": [
    "### Выделим значения\n",
    "\n",
    "Теперь давай отделим целевые значения *label* от характеристик.\n",
    "\n",
    "Мы будем использовать эти значения для обучения нашей модели:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "t2sluJdCW7jN"
   },
   "outputs": [],
   "source": [
    "train_labels = train_dataset.pop('Расход топлива')\n",
    "test_labels = test_dataset.pop('Расход топлива')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "mRklxK5s388r"
   },
   "source": [
    "### Нормализуем данные\n",
    "\n",
    "Давай еще раз взглянем на блок `train_stats` выше. Обрати внимание, что значения каждой характеристики измеряются по разному."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "-ywmerQ6dSox"
   },
   "source": [
    "Нормализация параметров данных, в которых используются разные единицы измерений - один из первых шагов подготовки данных к обучению. Несмотря на то, что модель конечно *может* стремиться к пределу без нормализации, но это излишне усложняет обучение, а также делает получившуюся модель зависимой от выбора единиц измерения входных данных.\n",
    "\n",
    "Статистику, полученную по данным из обучения, мы будем также использовать для данных из проверки. Так и задумано, так как модель еще не будет иметь никакой информации по проверочным данным."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "JlC5ooJrgjQF"
   },
   "outputs": [],
   "source": [
    "def norm(x):\n",
    "  return (x - train_stats['mean']) / train_stats['std']\n",
    "normed_train_data = norm(train_dataset)\n",
    "normed_test_data = norm(test_dataset)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "BuiClDk45eS4"
   },
   "source": [
    "Для обучения модели мы будем использовать обновленные, нормализованные данные.\n",
    "\n",
    "Внимание: статистика, используемая для нормализации входных данных так же важна, как и сами веса модели."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "SmjdzxKzEu1-"
   },
   "source": [
    "## Модель"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "6SWtkIjhrZwa"
   },
   "source": [
    "### Построим модель\n",
    "\n",
    "Теперь давай построим нашу модель. Мы будем использовать `Sequential` (последовательную) модель с двумя полносвязными Dense слоями, а выходящий слой будет возвращать одно постоянно изменяющееся значение. Все этапы построения модели мы опишем в функции `build_model`, так как позже мы создадим еще одну модель."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "c26juK7ZG8j-"
   },
   "outputs": [],
   "source": [
    "def build_model():\n",
    "  model = keras.Sequential([\n",
    "    layers.Dense(64, activation=tf.nn.relu, input_shape=[len(train_dataset.keys())]),\n",
    "    layers.Dense(64, activation=tf.nn.relu),\n",
    "    layers.Dense(1)\n",
    "  ])\n",
    "\n",
    "  optimizer = tf.train.RMSPropOptimizer(0.001)\n",
    "\n",
    "  model.compile(loss='mse',\n",
    "                optimizer=optimizer,\n",
    "                metrics=['mae', 'mse'])\n",
    "  return model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "cGbPb-PHGbhs"
   },
   "outputs": [],
   "source": [
    "model = build_model()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Sj49Og4YGULr"
   },
   "source": [
    "### Проверим модель\n",
    "\n",
    "Давай воспользуемся методом `.summary` чтобы посмотреть как выглядит наша модель:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "ReAD0n6MsFK-"
   },
   "outputs": [],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Vt6W50qGsJAL"
   },
   "source": [
    "\n",
    "Все готово, теперь мы можем опробовать нашу модель. Для начала попробуем небольшой батч из 10 примеров данных из тренировочного набора и попробуем предсказать результат."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "-d-gBaVtGTSC"
   },
   "outputs": [],
   "source": [
    "example_batch = normed_train_data[:10]\n",
    "example_result = model.predict(example_batch)\n",
    "example_result"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "QlM8KrSOsaYo"
   },
   "source": [
    "Похоже все работает правильно, модель показывает результат ожидаемой формы и класса."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "0-qWCsh6DlyH"
   },
   "source": [
    "### Обучим модель\n",
    "\n",
    "Мы будем обучать модель в течение 1000 эпох и фиксировать точность модели на тренирвочных и проверочных данных в объекте `history`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "sD7qHCmNIOY0"
   },
   "outputs": [],
   "source": [
    "# Выведем прогресс обучения в виде точек после каждой завершенной эпохи\n",
    "class PrintDot(keras.callbacks.Callback):\n",
    "  def on_epoch_end(self, epoch, logs):\n",
    "    if epoch % 100 == 0: print('')\n",
    "    print('.', end='')\n",
    "\n",
    "EPOCHS = 1000\n",
    "\n",
    "history = model.fit(\n",
    "  normed_train_data, train_labels,\n",
    "  epochs=EPOCHS, validation_split = 0.2, verbose=0,\n",
    "  callbacks=[PrintDot()])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "tQm3pc0FYPQB"
   },
   "source": [
    "Теперь давай сделаем визуализацию процесса обучения при помощи статистики из объекта `history`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "4Xj91b-dymEy"
   },
   "outputs": [],
   "source": [
    "hist = pd.DataFrame(history.history)\n",
    "hist['epoch'] = history.epoch\n",
    "hist.tail()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "B6XriGbVPh2t"
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def plot_history(history):\n",
    "  plt.figure()\n",
    "  plt.xlabel('Эпоха')\n",
    "  plt.ylabel('Среднее абсолютное отклонение')\n",
    "  plt.plot(hist['epoch'], hist['mean_absolute_error'],\n",
    "           label='Ошибка при обучении')\n",
    "  plt.plot(hist['epoch'], hist['val_mean_absolute_error'],\n",
    "           label = 'Ошибка при проверке')\n",
    "  plt.legend()\n",
    "  plt.ylim([0,5])\n",
    "  \n",
    "  plt.figure()\n",
    "  plt.xlabel('Эпоха')\n",
    "  plt.ylabel('Среднеквадратическая ошибка')\n",
    "  plt.plot(hist['epoch'], hist['mean_squared_error'],\n",
    "           label='Ошибка при обучении')\n",
    "  plt.plot(hist['epoch'], hist['val_mean_squared_error'],\n",
    "           label = 'Ошибка при проверке')\n",
    "  plt.legend()\n",
    "  plt.ylim([0,20])\n",
    "\n",
    "plot_history(history)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "AqsuANc11FYv"
   },
   "source": [
    "Полученный график показывает, что после нескольких сотен эпох наша модель улучшается совсем незначительно в процессе обучения. Давай обновим метод `model.fit` чтобы автоматически прекращать обучение как только показатель проверки *Val loss* не улучшается. Для этого мы используем функцию обратного вызова *callback*, которая проверяет показатели обучения после каждой эпохи. Если после определенного количество эпох нет никаких улучшений, то функция автоматически остановит его.\n",
    "\n",
    "Читай больше про функцию *callback* [здесь](https://www.tensorflow.org/versions/master/api_docs/python/tf/keras/callbacks/EarlyStopping)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "fdMZuhUgzMZ4"
   },
   "outputs": [],
   "source": [
    "model = build_model()\n",
    "\n",
    "# Параметр patience определяет количество эпох, которые можно пропустить без улучшений\n",
    "early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=50)\n",
    "\n",
    "history = model.fit(normed_train_data, train_labels, epochs=EPOCHS,\n",
    "                    validation_split = 0.2, verbose=0, callbacks=[early_stop, PrintDot()])\n",
    "\n",
    "plot_history(history)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "3St8-DmrX8P4"
   },
   "source": [
    "График показывает что среднее значение ошибки на проверочных данных - около 2 галлонов на милю. Хорошо это или плохо? Решать тебе.\n",
    "\n",
    "Давай посмотрим как наша модель справится на **наборе данных для проверки**, который мы еще не использовали после обучения:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "jl_yNr5n1kms"
   },
   "outputs": [],
   "source": [
    "loss, mae, mse = model.evaluate(normed_test_data, test_labels, verbose=0)\n",
    "\n",
    "print(\"Среднее абсолютное отклонение на проверочных данных: {:5.2f} галлон на милю\".format(mae))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "ft603OzXuEZC"
   },
   "source": [
    "### Делаем предсказания\n",
    "\n",
    "Наконец давай сделаем предсказания показателей расхода топлива, используя набор наши проверочные данные:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "Xe7RXH3N3CWU"
   },
   "outputs": [],
   "source": [
    "test_predictions = model.predict(normed_test_data).flatten()\n",
    "\n",
    "plt.scatter(test_labels, test_predictions)\n",
    "plt.xlabel('Истинные значения')\n",
    "plt.ylabel('Предсказанные значения')\n",
    "plt.axis('equal')\n",
    "plt.axis('square')\n",
    "plt.xlim([0,plt.xlim()[1]])\n",
    "plt.ylim([0,plt.ylim()[1]])\n",
    "_ = plt.plot([-100, 100], [-100, 100])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "f-OHX4DiXd8x"
   },
   "outputs": [],
   "source": [
    "error = test_predictions - test_labels\n",
    "plt.hist(error, bins = 25)\n",
    "plt.xlabel(\"Prediction Error [MPG]\")\n",
    "_ = plt.ylabel(\"Count\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "vgGQuV-yqYZH"
   },
   "source": [
    "## Заключение\n",
    "\n",
    "Это руководство познакомило тебя с несколькими способами решения задач регрессии.\n",
    "\n",
    "Ключевые моменты урока:\n",
    "\n",
    "* Mean Squared Error (MSE) (пер. \"Среднеквадратическая ошибка\") - это распространенная функция потерь, используемая для решения задач регрессии (отличная от задач классификации)\n",
    "* Показатели оценки модели для регрессии отличаются от используемых в классификации\n",
    "* Когда входные данные имеют параметры в разных форматах, каждый параметр должен быть нормализован\n",
    "* Если данных для обучения немного, используй небольшую сеть из нескольких скрытых слоев. Это поможет избежать переобучения\n",
    "* Используй метод ранней остановки - это очень полезная техника для избежания переобучения"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "basic-regression.ipynb",
   "private_outputs": true,
   "provenance": [],
   "toc_visible": true,
   "version": "0.3.2"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
